﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Xml;
using System.Text.RegularExpressions;

namespace HtmlToXml
{

    public class Tag
    {
        public Int32 Begin { get; set; }
        public Int32 End { get; set; }
        public String Text { get; set; }
        public String Name
        {
            get
            {
                String text = Text;
                if (String.IsNullOrEmpty(text))
                    return String.Empty;
                if (text.Contains(' '))
                    text = text.Substring(0, text.IndexOf(' '));
                else
                    text = text.Substring(0, text.Length - 1);
                return text.Substring(1).Replace("/", String.Empty);
            }
        }

        public Tag(String text = "", Int32 begin = 0, Int32 end = 0)
        {
            Begin = begin;
            End = end;
            if (!String.IsNullOrEmpty(text) && text[1] != '!')
                Text = text;
        }

        public static Tag GetNearestTag(String html, ref Int32 k)
        {
            Tag tag = new Tag();
        // 1. Определяем начало
        a1: ;
            while ((k < html.Length - 1) && html[k] != '<')
                k++;
            if (k < html.Length - 10 && html.Substring(k, 9) == "<![CDATA[")
            {
                k++;
                goto a1;
            }
            tag.Begin = k;
            tag.End = k;
        // 2. Доходим до конца
        a2: ;
            while ((tag.End < html.Length - 1) && html[tag.End] != '>')
            {
                if (html[tag.End] == '<')   // Если встречается '<' - это открытие тега
                {
                    if (tag.End > html.Length - 10 || html.Substring(tag.End, 9) != "<![CDATA[")
                        tag.Begin = tag.End;    // Меняем начало
                }
                tag.End++;
            }
            if (tag.End - 2 >= 0 && html.Substring(tag.End - 2, 3) == "]]>")
            {
                tag.End++;
                goto a2;
            }
            k = tag.End;
            // 3. Если начало и конец совпадают или конец не '>' - больше тегов нет 
            if (html[tag.End] != '>' || tag.Begin == tag.End)
                tag = null;
            tag.Text = html.Substring(tag.Begin, tag.End - tag.Begin + 1);
            return tag;
        }

        public Dictionary<String, String> Attributes
        {
            get
            {
                String tag = Text;
                Dictionary<String, String> attributs = new Dictionary<string, string>();
                if (tag.Contains("return showBox("))
                    tag = tag + "";
                Int32 k = 0;
                Int32 maxLength = tag.Length - 1;
                while (k < maxLength)
                {
                    if (tag[k] == ' ')
                    {
                        Int32 keyBegin = k + 1;
                        Int32 keyEnd = keyBegin;
                        while (keyEnd <  maxLength && tag[keyEnd] != '=')
                            keyEnd++;
                        String key = tag.Substring(keyBegin, keyEnd - keyBegin);
                        Int32 valueBegin = keyEnd + 1;
                        Char valueEndSymbol;
                        switch (tag[valueBegin])
                        {
                            case '"':
                                valueEndSymbol = '"';
                                break;
                            case '\'':
                                valueEndSymbol = '\'';
                                break;
                            default:
                                valueEndSymbol = ' ';
                                break;
                        }
                        Int32 valueEnd = valueBegin + 1;
                        while (valueEnd < maxLength)
                        {
                            Boolean isEndSymbol = (tag[valueEnd] == valueEndSymbol);
                            Boolean nextIsRightSymbol = true;
                            if(valueEndSymbol != ' ')   // if end symbol not space I expect one more sign for end
                                nextIsRightSymbol = tag[valueEnd + 1] == ' ' || tag[valueEnd + 1] == '>';
                            Boolean exit = isEndSymbol && nextIsRightSymbol;
                            if (exit == true)
                                break;
                            valueEnd++;
                        }
                        String value = tag.Substring(valueBegin, valueEnd - valueBegin);
                        #region Key and value modifications
                        if (key.Length >= "VK1290298570529".Length)                  // LOL delete this
                            key = "changed_atr_name";                                // LOL delete this
                        if (value[0] == '"' || value[0] == '\'')
                            value = value.Substring(1, value.Length - 1);
                        value = value.Replace("\"", "'");
                        #endregion
                        k = valueEnd;
                        if (tag[valueEnd] == ' ')
                            k--;
                        if (!String.IsNullOrEmpty(key) && attributs.ContainsKey(key) == false)
                            attributs.Add(key, value);
                    }
                    k++;
                }
/*
                String[] data = tag.Split(' ');
                foreach (String s in data)
                {
                    if (s.Contains('='))
                    {
                        Int32 indexOf = s.IndexOf('=');
                        String key = PrepareAttributeKey(s.Substring(0, indexOf));
                        String value = s.Substring(indexOf + 1).Replace("'", String.Empty).Replace("\"", String.Empty); 
                        value = value.Replace(">", String.Empty);
                        if(!String.IsNullOrEmpty(key) && attributs.ContainsKey(key)==false)
                            attributs.Add(key, value);
                    }
                }*/
                return attributs;
            }
        }

        public String GetTagWithXmlStyleAttributes()
        {
            Dictionary<String, String> attributs = Attributes;
            String newTagText = Text;
            if (newTagText.Contains(' '))
            {
                newTagText = newTagText.Substring(0, newTagText.IndexOf(' '));
                foreach (KeyValuePair<String, String> pair in attributs)
                {
                    String value = pair.Value;
                    newTagText += " " + String.Format("{0}=\"{1}\"",pair.Key, value);
                }
                newTagText += ">";
            }
            return newTagText;
        }

        private String PrepareAttributeKey(String key)
        {
            Regex regex = new Regex("(\\(|\\)|\\.|\\\'\\\"|\\;|\\:|\\/|\\&|\\#)");
            key = regex.Replace(key, String.Empty);
            return key;
        }

        public Boolean IsClosingTag
        {
            get
            {
                String tagText = this.Text;
                return (!String.IsNullOrEmpty(tagText) && (tagText[tagText.Length - 2] == '/' || tagText[1] == '/')) ? true : false;
            }
        }
    }
}
